package com.demo.job.listener;

import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerOnStateTransitionEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

/**
 * 熔断器事件监听器
 * 监听熔断器状态变化事件并进行日志记录和告警处理
 */
@Slf4j
@Component
public class CircuitBreakerEventListener {

    /**
     * 监听熔断器状态转换事件
     * @param event 熔断器状态转换事件
     */
    @EventListener
    public void onCircuitBreakerEvent(CircuitBreakerOnStateTransitionEvent event) {
        log.warn("熔断器状态变更: {} 从 {} 转换到 {}", 
                event.getCircuitBreakerName(),
                event.getStateTransition().getFromState(),
                event.getStateTransition().getToState());
        
        // 根据状态变化进行不同的处理
        CircuitBreaker.State toState = event.getStateTransition().getToState();
        String serviceName = event.getCircuitBreakerName();
        
        switch (toState) {
            case OPEN:
                // 熔断器开启，发送告警
                sendAlert(serviceName, "熔断器开启", "服务调用失败率过高，熔断器已开启");
                break;
            case HALF_OPEN:
                // 熔断器半开，记录信息
                log.info("熔断器半开: {} 开始尝试恢复服务调用", serviceName);
                break;
            case CLOSED:
                // 熔断器关闭，服务恢复
                log.info("熔断器关闭: {} 服务调用已恢复正常", serviceName);
                sendAlert(serviceName, "熔断器关闭", "服务调用已恢复正常");
                break;
            default:
                log.debug("熔断器状态变化: {} -> {}", serviceName, toState);
                break;
        }
    }

    /**
     * 发送告警通知
     * @param serviceName 服务名称
     * @param alertType 告警类型
     * @param message 告警消息
     */
    private void sendAlert(String serviceName, String alertType, String message) {
        // 这里可以实现具体的告警逻辑，如：
        // 1. 发送邮件通知
        // 2. 发送短信告警
        // 3. 推送到钉钉/企业微信
        // 4. 写入告警数据库
        // 5. 调用监控系统API
        
        log.error("🚨 服务告警 🚨");
        log.error("服务名称: {}", serviceName);
        log.error("告警类型: {}", alertType);
        log.error("告警消息: {}", message);
        log.error("告警时间: {}", java.time.LocalDateTime.now());
        
        // TODO: 在这里添加实际的告警实现
        // 例如：emailService.sendAlert(serviceName, alertType, message);
        // 例如：dingTalkService.sendMessage(serviceName, alertType, message);
    }
}